#include "tcpmodbdev.h"
#include "KgGlobalData.h"
#include "rtdb.h"
#include <math.h>
#include "tcpmodbdev.h"

#define RUN_LOG_MODBUS_PCS              190  //PCS modbus 报文
#define RUN_LOG_MESSAGE_PCS             200  //PCS操作报文
#define RUN_LOG_FAILED_PCS              210  //PCS操作失败报文
#define WAIT_DEV_TIME					1500 // added 2020-6-3 //3000
#define DEV_ADDR     1

void getSystemTime(char time_buf[50]);

void saveLogToBaDb(QString strLog);

quint16 getUint16(float fVal);
float getRealVal(quint16 uVal, float rate);

void PrintLog(char *str, char *pData, int length)
{
   //return;
    int i;
    printf("%s",str);
	for (i = 0; i < length; ++i)
		printf("%02x ",  *(pData+i));
	printf("\n");

}

CModbusFactory::CModbusFactory()
{

}

CModbusFactory::~CModbusFactory()
{

}
 
int CModbusFactory::addParam2Buffer(char* pData, quint32 uiParamVal)
{
	*pData = (char)(uiParamVal >> 24);

	++pData;
	*pData = (char)(uiParamVal >> 16);

	++pData;
	*pData = (char)(uiParamVal >> 8);

	++pData;
	*pData = (char)(uiParamVal);

	return  0;
}

int CModbusFactory::addParam2Buffer(char* pData, quint16 uiParamVal)
{
	*pData = (char)(uiParamVal >> 8);

	++pData;
	*pData = (char)(uiParamVal);

	return  0;
}

int CModbusFactory::addParam2Buffer(char* pData, float fParamVal)
{
	char aTemp[4];
	memcpy(aTemp, &fParamVal, 4);
	
	*pData = aTemp[3];
	++pData;
	*pData = aTemp[2];
	++pData;
	*pData = aTemp[1];
	++pData;
	*pData = aTemp[0];
	
	return 0;
}

int CModbusFactory::addParam2Buffer(char* pData, uchar ucParamVal)
{
   *pData = (char)(ucParamVal);
}

int CModbusFactory::addParam2BufferSmall(char* pData, quint16 uiParamVal)
{
	*pData = (char)(uiParamVal);

	++pData;
	*pData = (char)(uiParamVal >> 8);

	return  0;
}

int CModbusFactory::getParamFromBuffer(char* pData, qint16& uiParamVal)
{
	uiParamVal = (unsigned char)*pData;
	uiParamVal = uiParamVal * 256;

	++pData;

	uiParamVal += (unsigned char)*pData;

	return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, quint16& uiParamVal)
{
	uiParamVal = (unsigned char)*pData;
	uiParamVal = uiParamVal * 256;

	++pData;

	uiParamVal += (unsigned char)*pData;

	return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, quint32& uiParamVal)
{
	uiParamVal = (unsigned char)*pData;

	uiParamVal = uiParamVal * 256;
	++pData;
	uiParamVal += (unsigned char)*pData;

	uiParamVal = uiParamVal * 256;
	++pData;
	uiParamVal += (unsigned char)*pData;

	uiParamVal = uiParamVal * 256;
	++pData;
	uiParamVal += (unsigned char)*pData;

	return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, float& fParamVal) 
{
   // 解析大端格式数据 //FF C0 00 00 = nan (schneider-meter)
	char aTemp[4];
	aTemp[3] = *pData;
	++pData;
	aTemp[2] = *pData;
	++pData;
	aTemp[1] = *pData;
	++pData;
	aTemp[0] = *pData;

	// 无效数据处理
	if (0xFF == aTemp[3] && 0xC0 == aTemp[2]  && 0x00 == aTemp[1]  &&  0x00 == aTemp[0])
	{
	   fParamVal = 0;
	   return 0;
	}

	memcpy(&fParamVal, aTemp, 4);
	return 0;
}

int CModbusFactory::getParamFromBufferSmall(char* pData, float& fParamVal)
{
    // 解析小端格式数据	//00 00 C0 FF = nan
	char aTemp[4];
	aTemp[0] = *pData;
	++pData;
	aTemp[1] = *pData;
	++pData;
	aTemp[2] = *pData;
	++pData;
	aTemp[3] = *pData;
	
	// 无效数据处理
	if (0xFF == aTemp[3] && 0xC0 == aTemp[2]  && 0x00 == aTemp[1]  &&  0x00 == aTemp[0])
	{
	   fParamVal = 0;
	   return 0;
	}

	memcpy(&fParamVal, aTemp, 4);
	return 0;
} 

int CModbusFactory::formDatagram(quint16 usEvent, uchar uaAddr, uchar uaFuncCode, quint16 usStartReg, quint16 usRegNum, char* pSendDataBuf)
{
	int iLenVal = 0;
	quint16 usTemp = 0;

	addParam2Buffer(pSendDataBuf, usEvent);
	iLenVal += 2;

	usTemp = 0;
  	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2; //协议标识

	usTemp = 6; //长度
	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2;

	*(pSendDataBuf + iLenVal) = uaAddr;
	iLenVal += 1;

	*(pSendDataBuf + iLenVal) = uaFuncCode;
	iLenVal += 1;

	usTemp = usStartReg;
	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2;

	usTemp = usRegNum;
	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2;

	return iLenVal;
}

int CModbusFactory::formSetSinglegram(quint16 usEvent, uchar uaAddr, quint16 usRegAddr, quint16 usRegVal, char* pSendDataBuf)
{
	int iLenVal = 0;
	quint16 usTemp = 0;

	addParam2Buffer(pSendDataBuf, usEvent);
	iLenVal += 2;

	iLenVal += 2; //协议标识

	usTemp = 6; //长度
	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2;

	*(pSendDataBuf + iLenVal) = uaAddr;
	iLenVal += 1;

	*(pSendDataBuf + iLenVal) = 0x6;//uaFuncCode; 单项调节保持寄存器 06H
	iLenVal += 1;

	usTemp = usRegAddr;
	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2;

	usTemp = usRegVal;
	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2;

	return iLenVal;
}

int CModbusFactory::formSetMultgram(quint16 usEvent, uchar uaAddr, quint16 usRegAddr, quint16 regCount, quint16 *usRegValBuf, char* pSendDataBuf)
{
	int iLenVal = 0;
	quint16 usTemp = 0;

	addParam2Buffer(pSendDataBuf, usEvent);
	iLenVal += 2;

	iLenVal += 2; //协议标识

	usTemp = regCount*2+7; //长度
	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2;

	*(pSendDataBuf + iLenVal) = uaAddr;
	iLenVal += 1;

	*(pSendDataBuf + iLenVal) = 0x10;//uaFuncCode; 多项调节保持寄存器 10H
	iLenVal += 1;

	usTemp = usRegAddr;
	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2;

	usTemp = regCount;
	addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
	iLenVal += 2;

	*(pSendDataBuf + iLenVal) = regCount*2;
	iLenVal += 1;

	for (int i = 0; i < regCount; ++i)
	{
		addParam2Buffer(pSendDataBuf + iLenVal, usRegValBuf[i]);
		iLenVal += 2;
	}

	return iLenVal;
}

int CModbusFactory::analySetSingleDatagram(quint16 usSdEvent, char* pRecDataBuf, int iLen, quint16 usRegAddr, quint16 usRegVal, char devAddr)
{
    // some varibales
	int iRetVal = 0;
	int iInedx = 0;
	quint16 usEvent = 0;
	quint16 usLen = 0;
	uchar uaModbusAddr = 0;
	uchar uaFuncCode = 0;
	uchar uaByteNum = 0;

	uchar uaTemp8 = 0;
	quint16 usTemp16 = 0;
	quint32 uiTemp32 = 0;
	float fTemp = 0;

	quint16 usRepRegAddr =0;
	quint16 usRepRegVal =0;

	// 校验报文是否正确
	iInedx = 0;

	getParamFromBuffer(pRecDataBuf, usEvent);
	iInedx += 2;

	iInedx += 2; //协议标识 

	getParamFromBuffer(pRecDataBuf + iInedx, usLen);
	iInedx += 2;

	uaModbusAddr = (uchar)*(pRecDataBuf + iInedx);
	iInedx += 1;

	uaFuncCode = (uchar)*(pRecDataBuf + iInedx);
	iInedx += 1;

	if (devAddr != uaModbusAddr || iLen != usLen + 6 /*|| usLen != uaByteNum + 3*/) // 校验失败
	{
		return -2;
		//writeKgLogfile("==step1");
	}


	if (6!= uaFuncCode)//单项调节保持寄存器 06H
	{
		iRetVal = -3;
		//writeKgLogfile("==step2");
	}
	else if (usSdEvent != usEvent)//下设命令标识
	{
		iRetVal = -4;
		//writeKgLogfile("==step3");
	}
	else
	{
	    getParamFromBuffer(pRecDataBuf + iInedx, usTemp16);
		iInedx += 2;
		usRepRegAddr= usTemp16; //addr

		getParamFromBuffer(pRecDataBuf + iInedx, usTemp16);
		iInedx += 2;
		usRepRegVal= usTemp16; //value

		if (usRepRegAddr==usRegAddr && usRepRegVal==usRegVal)
		{
		    iRetVal = 0;
			//writeKgLogfile("==step4");
		}
		else
		{
		    //writeKgLogfile(QString("%1,%2,%3,%4").arg(usRepRegAddr).arg(usRegAddr).arg(usRepRegVal).arg(usRegVal));
			iRetVal = -5;
		}
	}
	return iRetVal;
}

int CModbusFactory::analySetMultDatagram(quint16 usSdEvent, char* pRecDataBuf, int iLen, quint16 usRegAddr, quint16 regCount)
{
	// some varibales
	int iRetVal = 0;
	int iInedx = 0;
	quint16 usEvent = 0;
	quint16 usLen = 0;
	uchar uaModbusAddr = 0;
	uchar uaFuncCode = 0;
	uchar uaByteNum = 0;

	uchar uaTemp8 = 0;
	quint16 usTemp16 = 0;
	quint32 uiTemp32 = 0;
	float fTemp = 0;

	quint16 usRepRegAddr =0;
	quint16 modifiedCount =0;

	// 校验报文是否正确
	iInedx = 0;

	getParamFromBuffer(pRecDataBuf, usEvent);
	iInedx += 2;

	iInedx += 2; //协议标识 

	getParamFromBuffer(pRecDataBuf + iInedx, usLen);
	iInedx += 2;

	uaModbusAddr = (uchar)*(pRecDataBuf + iInedx);
	iInedx += 1;

	uaFuncCode = (uchar)*(pRecDataBuf + iInedx);
	iInedx += 1;

	if (DEV_ADDR != uaModbusAddr || iLen != usLen + 6 /*|| usLen != uaByteNum + 3*/) // 校验失败
	{
		return -2;
	}


	if (0x10!= uaFuncCode)//多项调节保持寄存器 10H
	{
		iRetVal = -3;
	}
	else if (usSdEvent != usEvent)//多项调节保持寄存器标识
	{
		iRetVal = -4;
	}
	else
	{
		getParamFromBuffer(pRecDataBuf + iInedx, usTemp16);
		iInedx += 2;
		usRepRegAddr= usTemp16; //addr

		getParamFromBuffer(pRecDataBuf + iInedx, usTemp16);
		iInedx += 2;
		modifiedCount= usTemp16; //register count

		if (usRepRegAddr==usRegAddr && regCount==modifiedCount)
		{
			iRetVal = 0;
		}
		else
		{
			iRetVal = -4;
		}
	}
	return iRetVal;
}
  
//added by zyx 2019-7-3 begin
int CModbusFactory::analyReplayDatagram(char* pDataBuf, int iLen, SMdobusTcpReply& reply, int readRegCount)
{
   if (0 == pDataBuf || iLen < 11)
	{
		return -1;
	}
	reply.usEvent = 0;
	reply.usProto = 0;
	reply.usLen = 0;
	reply.uaAddr = 0;
	reply.uaFuncCode = 0;
	reply.usDataLen = 0;

	// Read Data
	int iInedx = 0;

	getParamFromBuffer(pDataBuf, reply.usEvent);
	iInedx += 2;

	getParamFromBuffer(pDataBuf + iInedx, reply.usProto);
	iInedx += 2;

	getParamFromBuffer(pDataBuf + iInedx, reply.usLen);
	iInedx += 2;

	reply.uaAddr = (uchar)*(pDataBuf + iInedx);
	iInedx += 1;

	reply.uaFuncCode = (uchar)*(pDataBuf + iInedx);
	iInedx += 1;

	quint16 usRegAddr  = 0;
	quint16 usRegCount = 0;

	// 校验报文是否正确
	if (2== reply.uaSendFuncCode)
	{
	    reply.usDataLen = (uchar)*(pDataBuf + iInedx);
	    iInedx += 1;
	
	    int dataLen = (readRegCount+1)/8;
		if (reply.usDataLen != dataLen)
		{
		    printf("first %d != %d\n", reply.usDataLen, dataLen);
			return -1;
		}
	}
	else if (3 == reply.uaFuncCode || 4 == reply.uaFuncCode)
	{
	    reply.usDataLen = (uchar)*(pDataBuf + iInedx);
	    iInedx += 1;

		if (reply.usDataLen != readRegCount*2)
		{
		    printf("sec %d != %d\n", reply.usDataLen, readRegCount*2);
			return -2;
		}
	}
	else if (6 == reply.uaFuncCode || 16 == reply.uaFuncCode)
	{
		getParamFromBuffer(pDataBuf + iInedx, usRegAddr);
	    iInedx += 2;

		getParamFromBuffer(pDataBuf + iInedx, usRegCount);
	    iInedx += 2;
	}
	else
		;
		
	//if (3 != reply.uaFuncCode && 4 != reply.uaFuncCode)
	if (reply.uaFuncCode != reply.uaSendFuncCode)
	{
	    printf("thd %d != %d\n", reply.uaFuncCode, reply.uaSendFuncCode);
		return -3;
	}

	if (6 == reply.uaFuncCode || 16 == reply.uaFuncCode)
	{
		if (reply.uaSendRegAddr != usRegAddr || readRegCount != usRegCount)
		{
		    printf("fourth error send regAddr:%d, regCount%d, read regAddr:%d, regCount%d\n", 
				reply.uaSendRegAddr, readRegCount, usRegAddr, usRegCount);
			return -4;
		}
		else
		{
		    printf("fourth right send regAddr:%d, regCount%d, read regAddr:%d, regCount%d\n", 
				reply.uaSendRegAddr, readRegCount, usRegAddr, usRegCount);
		}
	}

	return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, uchar& uiParamVal)
{
	uiParamVal = (unsigned char)*pData;
	return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, quint64& uiParamVal)
{
   quint32 big = 0;
   quint32 small = 0;
   getParamFromBuffer(pData,big);
   pData += 4;
   getParamFromBuffer(pData,small);
   uiParamVal = big*256*256*256*256 + small;
}

void get_current_time(int *year, int *month, int *day, int *hour, int *minu, int *sec)
{
 #ifdef XNLINUX
	time_t timep;
	struct tm *p;
	time(&timep);
	p=localtime(&timep);
	*year = p->tm_year+1900;
	*month =p->tm_mon+1;
	*day = p->tm_mday;
	*hour =p->tm_hour;
	*minu = p->tm_min;
	*sec = p->tm_sec; 
#endif
}

void getSystemTime(char time_buf[50])
{
	int year,month,day, hour, minu,sec;
	get_current_time(&year,&month,&day,&hour,&minu,&sec);
	sprintf(time_buf, "time:%04d-%02d-%02d %02d:%02d:%02d",year,month,day,hour,minu,sec);
}

int g_printRpCount = 0;
void TcpModbDev::SaveSendRecvLog( unsigned char *data, int dataLength, bool isSended)
{
	if (g_printRpCount < 30)
	{
		g_printRpCount += 1;
	}
	else
	{
		return;

	}

	UINT8 addr;
	char time_buf[50];
	char tmp[350];
	QString strLog;
	int i;

	if (dataLength >= 250)
		return;

	getSystemTime(time_buf); 
	if (isSended)
	   sprintf(tmp, "%s, TcpModbDev port:%d send data:", time_buf, m_usPort);//时间
	else
	   sprintf(tmp, "%s, TcpModbDev port:%d recv data:", time_buf, m_usPort);//时间
	strLog = tmp;

	for (i = 0; i < dataLength; ++i)//;
	{
		sprintf(tmp, "%02X ", data[i]);//以16进制占两位格式输出
		strLog += tmp;
	}

	 writeKgLogfile(strLog);
	 return;
}

TcpModbDev::TcpModbDev(QObject *parent)
	: QThread(parent)
{

	m_pDataBuf = new char[SNED_BUFFER_LENGHT];
	m_pSendBuf = new char[SNED_BUFFER_LENGHT];

	m_pModbusFactory = new CModbusFactory;
	m_pTcpClient = 0;
	
	m_strIP =  "127.0.0.1";
	m_usPort = 502;
	m_bTcpConnected = false;

	m_uaFuncCode = 0;
	m_iErrNum = 0;
 
	m_saveRdCount = 0; 

	m_connErrorLog = 99;

	//QObject::connect(this, SIGNAL(addLog(int, const QString&)), parent, SLOT(addUserSrvLog(int, const QString&)));

}

TcpModbDev::~TcpModbDev()
{
	if (m_pDataBuf)
	{
		delete []m_pDataBuf;
		m_pDataBuf = 0;
	}

	if (m_pSendBuf)
	{
		delete []m_pSendBuf;
		m_pSendBuf = 0;
	}

	if (m_pModbusFactory)
	{
		delete m_pModbusFactory;
		m_pSendBuf = 0;
	}
}

void TcpModbDev::setPara(QString strIp, int port)
{
   m_strIP = strIp;
   m_usPort = port; 
}

void TcpModbDev::disconnected()
{
	m_bTcpConnected = false;
	printf("TcpModbDev::disconnected()\n"); 
}

void TcpModbDev::KgSleep(int timespan)
{
    msleep(timespan);
}

int TcpModbDev::sendRecvData(char* pataBuf, int regCount, int iRetVal)
{
    //this->msleep(600); //不加延时，USR-668有时会读取数据失败，虽然串口设备已回复数据 added 2020-6-3
    this->msleep(100);
    int iIndexStep = 1000;
	SaveSendRecvLog((unsigned char *)pataBuf, iRetVal, true);
	
	if (iRetVal != m_pTcpClient->write(pataBuf, (qint64)iRetVal))
	{
		++m_iErrNum;
		printf("Write data to dev FAILED.\n");
		//emit addLog(RUN_LOG_FAILED_PCS, QString("Write data to dev(%1:%2) FAILED.").arg(m_strIP).arg(m_usPort));
	}
	else
	{
		m_pTcpClient->flush();
		// receive data
		if (!m_pTcpClient->waitForReadyRead(WAIT_DEV_TIME)) // timeout 
		{
			++m_iErrNum;
			//printf("iErrNum:%d\n", m_iErrNum);
			//emit addLog(RUN_LOG_FAILED_PCS, QString("Read data (%1:%2) Timeout.").arg(m_strIP).arg(m_usPort));
			printf("Read data timeout.\n");
		}
		else
		{
			memset(m_pDataBuf, 0, SNED_BUFFER_LENGHT);
			//printf("TcpModbDev step1\n");
			iRetVal = m_pTcpClient->read(m_pDataBuf, SNED_BUFFER_LENGHT);
			//printf("TcpModbDev step2\n");
			m_iErrNum = 0; //分析正确清空  此处要清0，否则读取失败就会累计，从而关闭连接 2020-4-16
			
			if (iRetVal > 0) // read OK
			{
				//printf("TcpModbDev step3,iRetVal:%d\n", iRetVal);
				SaveSendRecvLog((unsigned char *)m_pDataBuf, iRetVal, false);
				//printf("TcpModbDev step4\n");
				SMdobusTcpReply reply;
				reply.uaSendFuncCode = m_uaFuncCode;
				reply.uaSendRegAddr =  m_usRegAddr;
				if (0 == m_pModbusFactory->analyReplayDatagram(m_pDataBuf,iRetVal,reply,regCount))
				{
				   //printf("TcpModbDev step5\n");
				   return 0;
				}
				//printf("TcpModbDev step6\n");
			}
			else
			{
			}
		} 
   }
   return -1;
}

int g_iEvent = 0;
void TcpModbDev::KgReadDevData(BrotherBaData &dev)
{
    int iLenVal = 0;
	int regCount = 0;
    int iInedx = 0;
	QString str;

	str = QString("read AC data (devAddr:%1)").arg(dev.devAddr);
	writeKgLogfile(str);
	
	regCount = 2; //2个IO数据
	m_uaFuncCode = 3;
	m_usRegAddr = 40;
	if (++g_iEvent > 100)
		g_iEvent = 1;
	iLenVal =  m_pModbusFactory->formDatagram(g_iEvent, dev.devAddr, m_uaFuncCode, m_usRegAddr, regCount, m_pSendBuf);
	if (0 == sendRecvData(m_pSendBuf,regCount,iLenVal))
	{
	    readDevData1(m_pDataBuf,0,dev); //注意是m_pDataBuf, 而不是m_pSendBuf
		dev.failedCount = 0;
		writeKgLogfile(QString("||||||Read Dev data1 OK (devAddr:%1) xfState:%2, ohterState:%3.")
			.arg(dev.devAddr).arg(dev.xfState).arg(dev.otherState));
	} 
	else
	{
	    if (dev.failedCount < 1000)
		{
	    	dev.failedCount += 1;
		}
		//writeKgLogfile(QString("Read Dev data1 failed (devAddr:%1) m_iErrNum:%2").arg(dev.devAddr).arg(m_iErrNum));
	}
}

int g_heartbeat = 1;
int g_testLogCount = 0;
int g_testLogSecCount = 0;
/*
usStackHoldTemp[35]	电池组总电压 V
usStackHoldTemp[36]	电池组总电流 A
usStackHoldTemp[37]	SOC	 0.1
usStackHoldTemp[38]	SOH	 0.1
usStackHoldTemp[39]	电池组最大允许充电电流	A
usStackHoldTemp[40]	电池组最大允许放电电流	A
usStackHoldTemp[41]	电池组最大允许充电功率	kW
usStackHoldTemp[42]	电池组最大允许放电功率	kW
usStackHoldTemp[43]	无	BMS总状态	0x1111禁充 0x2222禁放 0x5555告警 0xAAAA故障 0xBBBB正常
usStackHoldTemp[44]	无	主接触器状态	1-闭合 2-断开
usStackHoldTemp[45]	无	轻度告警字	Bit0:单体SOC过高 ...Bit15:放电过流
usStackHoldTemp[46]	无	中度告警字	Bit0:单体SOC过高 ...Bit15:放电过流
usStackHoldTemp[47]	无	严重告警字	Bit0:单体SOC过高 ...Bit15:放电过流
usStackHoldTemp[48]	无	BMS状态字	"Bit0:1-BMS与EMS通信故障 0-BMS与EMS通信正常
                                  Bit2-Bi3:0-无    1-充满    2-放空"
usStackHoldTemp[49]	心跳	1-255	
*/
void TcpModbDev::writeSlaveData()// 从机写入数据给主机
{
    int pos = 0;
	int iLenVal = 0;
	quint16 dataBuf[50];
	memset(dataBuf, 0,sizeof(dataBuf));

	/*
	KgGlobalData::ms_pStack->fStackVol = 600;
	KgGlobalData::ms_pStack->fStackCur = -12;
	KgGlobalData::ms_pStack->fStackSoc = 30;
	KgGlobalData::ms_pStack->fStackSoh = 100;
	KgGlobalData::ms_pStack->fBankMaxChargeCurrent = 20;
	KgGlobalData::ms_pStack->fBankMaxDischargeCurrent = 20;
	*/
	
	//quint16 usStackHoldTemp[50]; //30 - 79  
	dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fStackVol); //usStackHoldTemp[35]
	dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fStackCur); 
	dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fStackSoc*10); 
	dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fStackSoh*10); 
	dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fBankMaxChargeCurrent); //usStackHoldTemp[39]
	dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fBankMaxDischargeCurrent); //usStackHoldTemp[40]
	dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fBankMaxChargePower); //usStackHoldTemp[41]
	dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fBankMaxDischargePower); //usStackHoldTemp[42]
	dataBuf[pos++] = KgGlobalData::ms_pStack->usStackState; //usStackHoldTemp[43]  BMS总状态
	dataBuf[pos++] = 0; //getContactorState(); //usStackHoldTemp[44] 主接触器状态	1-闭合 2-断开
	dataBuf[pos++] = 0; //getAlarmWord(1); //usStackHoldTemp[45] 轻度告警字
	dataBuf[pos++] = 0; //getAlarmWord(2); //usStackHoldTemp[46] 中度告警字
	dataBuf[pos++] = 0; //getAlarmWord(3); //usStackHoldTemp[47] 严重告警字
	
	// BMS状态字 Bit0:1-BMS与EMS通信故障 0-BMS与EMS通信正常              // usStackHoldTemp[48]
    //           Bit2-Bi3:0-无    1-充满    2-放空
	dataBuf[pos++] = 0; //getBmsState(); //BMS状态字
	
	dataBuf[pos++] = g_heartbeat; //心跳     // usStackHoldTemp[49]
	if (++g_heartbeat > 255)
	{
		g_heartbeat = 1;
	}

   uchar uaAddr = 1;
   m_uaFuncCode = 0x10;
   m_usRegAddr = 65;
   quint16 regCount = pos;
   iLenVal =  m_pModbusFactory->formSetMultgram(50, uaAddr, m_usRegAddr, regCount, dataBuf, m_pSendBuf);
   if (0 == sendRecvData(m_pSendBuf,regCount,iLenVal))
   {
	   if (g_testLogSecCount < 100)
	   	{
	   		g_testLogSecCount += 1;
			writeKgLogfile(QString("============writeSlaveData  OK (devAddr:1)."));
	   	}
   } 
   else
   {
	   writeKgLogfile(QString("============writeSlaveData  failed (devAddr:1)."));
   }
}

/*
新疆盛全主机BA			
usStackHoldTemp[0]		从机BA数据写入标志	1-从机BA数据写入标志                0-没有写入
usStackHoldTemp[1]		从机BA电池最高温度	放大10倍
usStackHoldTemp[2]		从机BA电池最低温度	放大10倍
usStackHoldTemp[3]		从机BA电池平均温度	放大10倍
*/
void TcpModbDev::writeMinMaxTempData() // added 2023-11-28
{
   int iLenVal = 0;
   int iInedx = 0;
   QString str;

   if (g_testLogCount < 100)
   	{
   		g_testLogCount += 1;
		writeKgLogfile( QString("writeMinMaxTempData"));
   	}

   float fMaxSglTemp = 0; //getMaxSglTemp();
   float fMinSglTemp = 0; //getMinSglTemp();
   float fAvgSglTemp = 0; //getAvgSglTemp();

   quint16 dataBuf[10] = {0,0,0,0,0};
    if (fMaxSglTemp == fMinSglTemp) // 温度数据无效
   	{
   	   dataBuf[0] = 0; //标记无效
   	}
    else
   	{
   	   dataBuf[0] = 1; //标记有效
   	}
   dataBuf[1] = getUint16(fMaxSglTemp * 10);
   dataBuf[2] = getUint16(fMinSglTemp * 10);
   dataBuf[3] = getUint16(fAvgSglTemp * 10);
   
   uchar uaAddr = 1;
   m_uaFuncCode = 0x10;
   m_usRegAddr = 30;
   quint16 regCount = 4;
   // Send:00 32 00 00 00 0F 01 10 00 1E 00 04 08 | 00 01 01 5E 00 E1 01 00
   // Recv:00 32 00 00 00 06 01 10 00 1E 00 04
   //printf("===================1\n");
   iLenVal =  m_pModbusFactory->formSetMultgram(50, uaAddr, m_usRegAddr, regCount, dataBuf, m_pSendBuf);
   //printf("===================2\n");
   if (0 == sendRecvData(m_pSendBuf,regCount,iLenVal))
   {
	   if (g_testLogCount < 100)
	   	{
	   		g_testLogCount += 1;
			writeKgLogfile(QString("============writeMinMaxTempData  OK (devAddr:1)."));
	   	}
   } 
   else
   {
	   writeKgLogfile(QString("============writeMinMaxTempData  failed (devAddr:1)."));
   }
}


void InitDevData()
{
    BrotherBaData &devData = g_brotherBaData;//KgGlobalData::ms_brotherBaData;
	//devData.xfSpray = 0;
	memset(&devData, 0,  sizeof(BrotherBaData));
	devData.bReaded = false;
	devData.failedCount = 1000; //接收数据失败次数
	devData.devAddr = 1;
}

void TcpModbDev::JudgeDevConnError(BrotherBaData &dev)
{
	// 这里只输出日志，不参与策略 2021-1-7
	if (dev.failedCount >= 15)
	{
		if (0 == dev.connError || 99 == dev.connError) // modified 2023-2-17
		{
		    //QString strLog = QString("设备(%1,%2)通迅故障.").arg(m_strIP).arg(m_usPort);
			//saveLogToBaDb(strLog); 
		}
		dev.connError = 1;
	}
	else if (dev.failedCount < 1)
	{
		if (1 == dev.connError)
		{
			//QString strLog = QString("设备(%1,%2)通迅恢复.").arg(m_strIP).arg(m_usPort);
			//saveLogToBaDb(strLog); 
		}
		dev.connError = 0;
	}
	else
	{
		writeKgLogfile(QString("===============failedCount:%1 connError:%2.")
		.arg(dev.failedCount).arg((int)dev.connError));
	}
}

int g_readDevCount = 0;//程序刚运行时计数
void TcpModbDev::run()
{
	char *pData;
	int i;
	int k;
	int iIndexStep = 50;
	int iRetVal = -1;
	m_iErrNum = 0;
	unsigned int runingTime = 0;//记录运行时间
	
	int failedCount = 0;
	m_pTcpClient = new QTcpSocket;//(this);
	QObject::connect(m_pTcpClient, SIGNAL(disconnected()), this, SLOT(disconnected()));
	sleep(1);
	printf("********TcpModbDev::run()\n");
	
	InitDevData();

	CBattStack *pStack = KgGlobalData::ms_pRTDB->getStack(0);
	if (0 == pStack)
	{
	   //continue;
	}
	
	//pStack->fStackTemp[0] = 13; //testing
	//pStack->fStackTemp[1] = 16;
	//pStack->usStackTemp[28] = 280; //testing
	//pStack->usStackTemp[29] = 290;
	int m_connFailedCount = 0;
	
	while(1)
	{
		msleep(100);
		if (runingTime < 180 * 1000)//最多记录180秒
		   runingTime += 30;
		
		if (!m_bTcpConnected)
		{
			//if (0 != m_pTcpClient)
			//	m_pTcpClient->deleteLater();
			// connect to server
			emit addLog(RUN_LOG_MESSAGE_PCS, QString("Try to connnect USR(%1:%2)...").arg(m_strIP).arg(m_usPort));
			m_pTcpClient->connectToHost(m_strIP, m_usPort);
			if (!m_pTcpClient->waitForConnected(2000)) 
			{
				++failedCount;
				emit addLog(RUN_LOG_FAILED_PCS, QString("Try to connnect USR(%1:%2) FAILED.(Err Code:%4 Err Info:%5").arg(m_strIP).arg(m_usPort).arg(m_pTcpClient->error()).arg(m_pTcpClient->errorString()));
				//++m_connFailedCount;
				//if (m_connFailedCount >= 5)
				//{
					m_connFailedCount = 0;
					if (0 == m_connErrorLog || 99 == m_connErrorLog) // modified 2023-2-17
					{
					    if (KgGlobalData::ms_devNo >= 2)// modified 2023-12-30
					    {
					   	 	QString strLog = kgConvert("连接主机(%1,%2)失败.").arg(m_strIP).arg(m_usPort);
							saveLogToBaDb(strLog);
					    }
						else
						{
							QString strLog = kgConvert("连接从机(%1,%2)失败.").arg(m_strIP).arg(m_usPort);
							saveLogToBaDb(strLog);
						}
						
						QString strLog = QString("********connnect failed.");
						writeKgLogfile(strLog);
					}
					m_connErrorLog = 1;
				//}

				

				BrotherBaData &dev = g_brotherBaData;//KgGlobalData::ms_brotherBaData;
				//tmpHumd.connError = 1;
// modified 2023-2-17 原来是1-故障，则保持
				// TCP连接断开时，TEMPHD通信故障没有报，则恢复时也不要报恢复，所以要改为99
				if (0 == dev.connError)
				    dev.connError = 99;
				
				dev.failedCount = 1000;
				//strLog = QString("====BrotherBaData connError=%1.").arg(dev.connError);
				//writeKgLogfile(strLog);

		        //msleep(3*1000);
			    continue;
			}
			else
			{
				failedCount = 0;
				m_connFailedCount = 0;
				emit addLog(RUN_LOG_MESSAGE_PCS, QString("Connnect to BA(%1:%2) OK.").arg(m_strIP).arg(m_usPort));
				writeKgLogfile(QString("Connnect to BA  OK."));
				m_bTcpConnected = true;
				
				//pPcsInfo->onlineState = 1;//在线
				if (1 == m_connErrorLog) // modified 2023-2-17
				//if (1 == m_connErrorLog || 99 == m_connErrorLog) 
				{
					//QString strLog = QString("连接USR-580(地址:%1,端口:%2)成功.").arg(m_strIP).arg(m_usPort);
				     if (KgGlobalData::ms_devNo >= 2)// modified 2023-12-30
				     {
				     	QString strLog = kgConvert("连接主机(%1,%2)成功.").arg(m_strIP).arg(m_usPort);
					    saveLogToBaDb(strLog);
				     }
					 else
					 {
						 QString strLog = kgConvert("连接从机(%1,%2)成功.").arg(m_strIP).arg(m_usPort); 
						 saveLogToBaDb(strLog);
					 }
				}
				m_connErrorLog = 0;
			}
		}
		else
		{ 
			if (KgGlobalData::ms_devNo >= 2)// modified 2023-12-30
			{
			   //writeMinMaxTempData(); //从机BA电池最高最低温度 写入主机 (新疆盛全)
			   KgReadDevData(g_brotherBaData); 
			}
	       
		    if (KgGlobalData::ms_devNo >= 2)// modified 2023-12-30
		    {
		    	//writeSlaveData(); //从机写入数据给主机,供主机汇总 (楚能华锐)
		    }
			
			JudgeDevConnError(g_brotherBaData); //KgGlobalData::ms_brotherBaData
		   
			//writeKgLogfile("=======================end");
	           
			if (g_readDevCount < 100)
				g_readDevCount += 1;
		}
		 
		if (m_iErrNum >= 7)// modified 2023-4-19
		{
			writeKgLogfile(QString("******** m_pTcpClient->close()"));
			
			m_pTcpClient->close();
			m_bTcpConnected = false;
			m_iErrNum = 0;
			emit addLog(RUN_LOG_FAILED_PCS, QString("Dev(%1:%2) Disconnected FORCIBLY.").arg(m_strIP).arg(m_usPort));
		}
		
		//延时0.5秒
	    for (i = 0; i < 5; ++i)
		{ 
	        msleep(100);
		}
	}
}

void TcpModbDev::readReplyHead(char* pDataBuf, SMdobusTcpReply &reply, int &iInedx)
{
    m_pModbusFactory->getParamFromBuffer(pDataBuf, reply.usEvent);
	iInedx += 2;

	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, reply.usProto);
	iInedx += 2;

	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, reply.usLen);
	iInedx += 2;

	reply.uaAddr = (uchar)*(pDataBuf + iInedx);
	iInedx += 1;

	reply.uaFuncCode = (uchar)*(pDataBuf + iInedx);
	iInedx += 1;

	reply.usDataLen = (uchar)*(pDataBuf + iInedx);
	iInedx += 1;
}

int g_readCount = 0;
int g_printDhCount = 0;
void TcpModbDev::readDevData1(char* pDataBuf, int iRetVal, BrotherBaData &dev)
{
	int iInedx = 0;
		
    SMdobusTcpReply reply;
	readReplyHead(pDataBuf,reply,iInedx);
	CBattStack *pStack = KgGlobalData::ms_pStack;
	CBAComReg *pBAComReg = KgGlobalData::ms_pRTDB->getBAComReg(0);
	

    if (g_printDhCount < 50)
	{
		g_printDhCount += 1;
		//printf("===========Now  %02d dhdata, thunder:%d,%d, door:%d, xfData:%d-%d-%d, powOff:%d, upsError:%d.\n",
		//	g_printDhCount, dev.aZlThunder, dev.aJlThunder, dev.aDoorAlarm,
		//	dev.aFireWarn,dev.aFireAction,dev.aFireFault,dev.aJlDropElec,dev.aUpsError);
	}

    quint16 uiParamVal = 0;
	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //
	iInedx += 2;
	//dev.aZlThunder = uiParamVal; 
	quint16 xfAlarmWord = uiParamVal;
	dev.xfState = uiParamVal;

	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //
	iInedx += 2; 
	//dev.aJlThunder = uiParamVal;
	quint16 otherWord = uiParamVal;
	dev.otherState = uiParamVal;
	
	quint16 xfAlarm = ((xfAlarmWord & 1) > 0) ? 1: 0;
	quint16 xfSprayAlarm = ((xfAlarmWord & 2) > 0) ? 1: 0;
	quint16 xfFaultAlarm = ((xfAlarmWord & 4) > 0) ? 1: 0;
	quint16 xfManuAuto = ((xfAlarmWord & 8) > 0) ? 1: 0;
	
	if (1 != pStack->aFireAction && 1 == xfSprayAlarm) // added 2024-1-6
	{
		saveLogToBaDb(kgConvert("主机发生消防二级告警."));
	}

	if (1 == pStack->aFireAction && 1 != xfSprayAlarm)
	{
		saveLogToBaDb(kgConvert("主机消防二级告警结束."));
	}
	
	if (1 == xfSprayAlarm)
	{
		pStack->aFireAction = 1;
	}
	else
	{
		pStack->aFireAction = 0;
	}
	

	/*
	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //集装箱门禁
	iInedx += 2; 
	dev.aDoorAlarm = uiParamVal;

	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //消防告警
	iInedx += 2; 
	dev.aFireWarn = uiParamVal;

	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //消防动作
	iInedx += 2; 
	dev.aFireAction = uiParamVal;

	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //消防故障
	iInedx += 2; 
	dev.aFireFault = uiParamVal;

	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //交流失电
	iInedx += 2; 
	dev.aJlDropElec = uiParamVal;

	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //UPS故障
	iInedx += 2; 
	dev.aUpsError = uiParamVal;
	*/

	if (g_printDhCount < 50)
	{
		g_printDhCount += 1;
		//printf("===========Read %02d dhdata, thunder:%d,%d, door:%d, xfData:%d-%d-%d, powOff:%d, upsError:%d.\n",
		//	g_printDhCount, dev.aZlThunder, dev.aJlThunder,dev.aDoorAlarm,
		//	dev.aFireWarn,dev.aFireAction,dev.aFireFault,dev.aJlDropElec,dev.aUpsError);
	}
			
 
	/*if (1 != pStack->usStackHoldTemp[33] && 1 == uiParamVal) // added 2024-1-6
	{
		if (KgGlobalData::ms_devNo >= 2) // 当前BA为从机
			saveLogToBaDb(QString("主机发生保护故障."));
		else
			saveLogToBaDb(QString("从机发生保护故障."));
	}
	
	if (1 == pStack->usStackHoldTemp[33] && 1 != uiParamVal)
	{
		if (KgGlobalData::ms_devNo >= 2)// 当前BA为从机
			saveLogToBaDb(QString("主机保护故障结束."));
		else
			saveLogToBaDb(QString("从机保护故障结束."));
	}
	
	pStack->usStackHoldTemp[33] = uiParamVal; //另一BA是否有故障标志 // added 2023-12-30
	
	if (g_printDhCount < 50)
	{
		printf("******************usStackHoldTemp[33]:%d\n", pStack->usStackHoldTemp[33]);
	}
	else
	{
		if (pStack->usStackHoldTemp[33] > 0)
		{
			printf("******************usStackHoldTemp[33]:%d\n", pStack->usStackHoldTemp[33]);
		}
	}

	if (0 == g_readCount && 1 == KgGlobalData::ms_syncIODevData)
	{
		g_readCount += 1;
		QString strLog = QString("读取到主BA动环信息:%1-%2-%3-%4-%5-%6-%7-%8.")
			.arg(dev.aZlThunder).arg( dev.aJlThunder).arg(dev.aDoorAlarm)
			.arg(dev.aFireWarn).arg(dev.aFireAction).arg(dev.aFireFault)
			.arg(dev.aJlDropElec).arg(dev.aUpsError);
		saveLogToBaDb(strLog);
	}
	*/
}

/*
void TcpModbDev::readDevData2(char* pDataBuf, int iRetVal, BrotherBaData &dev)
{
	int iInedx = 0;
		
    SMdobusTcpReply reply;
	readReplyHead(pDataBuf,reply,iInedx);

    quint16 uiParamVal;
	float fVal = 0;
	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, fVal); //消防喷洒
	iInedx += 4;
	dev.xfSpray = fVal; 

	m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, fVal); //可燃气体
	iInedx += 2; 
	dev.gasAlarm = fVal;

	//QString strLog = QString("readDevData1===================%1, %2.").arg(dev.xfSpray).arg(dev.gasAlarm);
	//writeKgLogfile(strLog);
}
*/

BrotherBaData g_brotherBaData;
QString g_brotherBaIp; //另一台BA的IP
int g_brotherBaPort = 0; //另一台BA的端口
